/**
    Copyright (c) 2010-2011 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

/**
    @file   
    @brief  Mandelbrot compute shader.
    @date   2010/01/23
*/

RWStructuredBuffer<float4> output : register (u0);

cbuffer cb : register( b0 )
{
     // bounds of the complex number plane
    float fMinRe;
    float fMaxRe;
    float fMinIm;
    float fMaxIm;
    
    // step size for the complex number plane
    float fStepRe;
    float fStepIm;

    // width*height of the data buffer
    int        nSize;

    // width of the data buffer
    int        nWidth;
    
    // maximum iterations to decide whether an complex number is in the mandelbrot set.
    int        nMaxIterations;    
    
    int  padding[ 3 ];        // constant buffer ByteWidth has to be multiple of 16
};

[numthreads(16, 16, 1)]
void MandelbrotDirectCompute( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
    const float x = DTid.x;
    const float y = DTid.y;

    int nIteration=0;
            
    float4 color = float4( 0.0f, 0.0f, 0.0f, 1.0f );
    
    float cIm = fMaxIm - y*fStepIm;
    float cRe = fMinRe + x*fStepRe;

    float zRe = cRe;
    float zIm = cIm;
            
    for( nIteration=0; nIteration<nMaxIterations; ++nIteration )
    {
        float zRe2 = zRe*zRe;
        float zIm2 = zIm*zIm;
                
        /// check whether absolute value of z has gotten bigger than 2
        if( zRe2 + zIm2 > 4 ) {
            break;
        }

        // calculate next z(n)
        zIm = 2*zRe*zIm + cIm;
        zRe = zRe2-zIm2 + cRe;
    }
                        
    if( nIteration != nMaxIterations ) { 
        if( nIteration < nMaxIterations/2 ) {
            color = float4( nIteration / ((float)( nMaxIterations )/2.0f), 0.0f, 0.0f, 1.0f );
        }
        else {
            float fLerp = ( nMaxIterations-nIteration ) / ((float)( nMaxIterations )/2.0f);
            //color = float4( 1.0f, 0.0f, 0.0f, 1.0f )*(1.0f-fLerp)+float4( 1.0f, 1.0f, 1.0f, 1.0f )*( fLerp );
            color = lerp( float4( 1.0f, 0.0f, 0.0f, 1.0f ),float4( 1.0f, 1.0f, 1.0f, 1.0f ), fLerp );
        }    
    }

    const int nIndex = x+y*nWidth; 

    if( nIndex < nSize && x < nWidth ) {
        output[ nIndex ] = color;
    }
}
